Client Side Expressions, Validation, and Calculated Fields

Description

A number of properties for controls can be configured using javascript, this includes Validation, Show/Hide and Enable expressions, and Calculated Fields. Javascript functions for properties usually take a few parameters and return the value that defines the state of the parameter.

Validation Javascript

Validation in Alpha Anywhere is very powerful. Using a combination of Client-Side javascript and Server-Side Xbasic, you can implement incredibly complex validation criteria with relative ease. Alpha handles displaying the errors to the user. All you need to provide are the rules.

Validation Javascript is defined with javascript. The javascript is run whenever the control's onBlur event fires. Validation Javascript is not executed if the user never interacts with the control. You will need to use Validation Rules or other methods if you want controls in your UX component to be validated before executing some other action, such as submitting the data back to the server.

In your javascript for Validation Javascript, you have access to the value in the control via the data variable. data is a string, so you may need to convert the value to a different type using either Alpha's $u.s.toNum, $u.s.toBool functions or some other method. Alpha expects the Validation Javascript to return an error message or the value false. If you return an error message, the error will be shown to the user and visual indicators will appear in the UX component indicating what control has the error.

Client-Side Expressions

Listed in a control's Client Side Properties, there are several Client-Side Expressions available: Show/hide expression, Enable expression, and Readonly expression. Expressions are built using a SQL-like syntax. They can reference control values in the UX, some properties of the UX, and functions. There are a set of predefined functions available for use. You can also write your own javascript functions to use in your expressions. AGE > 18 and hasValidName(NAME)

function hasValidName(name) {
    if ($u.s.aTrim(name).length > 0) {
        return true;
    }
    return false;
}

It may be tempting to move all expression logic into a function and use {dialog.object}.getValue(). If an expression doesn't reference any controls in an UX, though, the expression will rarely be evaluated. Suppose the following expressions have been defined for two buttons. Each expression call a user-defined javascript function: evalMyExp1()

evalMyExp2(NAME)

In evalMyExp1, {dialog.object}.getValue('NAME') is called to get the value in the 'NAME' control.

function evalMyExp1() {
    var name = {dialog.object}.getValue('NAME');
    if ($u.s.aTrim(name).length > 0) {
        return true;
    }
    return false;
}

evalMyExp2, however, requires 'NAME' to be passed in as a parameter.

function evalMyExp2(name) {
    if ($u.s.aTrim(name).length > 0) {
        return true;
    }
    return false;
}

Both functions perform the same calculation on the same data, the 'NAME' control; however, both expressions are not called when the data, 'NAME', is modified. Only the expression calling evalMyExp2 will be executed after the value in the 'NAME' control changes. Since the evalMyExp1 expression doesn't reference any controls, the UX component doesn't know it should be called when 'NAME' is modified.

Expressions that don't reference any controls in a component are only called when Client Side computations are recalculated. This usually only occurs when a component is first rendered or when data in a component is re-populated in some fashion. You can force expressions to be re-evaluated using {dialog.Object}.refreshClientSideComputations(), but this is not the ideal solution. It's best to include controls as part of your expressions.

If you use javascript to manipulate the state of a control, such as the Action Javascript "Toggle display of a DIV or container" or writing your own javascript function to enable/disable a control as part of another event, do not define an expression for the corresponding property you plan to manipulate. A common mistake is setting a control's Show/hide expression to "1=2" when the UX component is first rendered and then using javascript elsewhere to display the container. Unfortunately, what often happens is the container will disappear seemingly at random. This is usually caused by calls to methods in {dialog.object} that trigger recalculation of the UX component's Client Side computations. "1=2" will always be false, so when the Show/hide expression is re-evaluated by the UX component, it concludes the control should be hidden. If you want a control to be hidden on initial render of a UX component, use styles or add javascript in one of the Client Side Events, such as onInitializeComplete, to hide the control.

Show/Hide Expression: User Defined Javascript event

For the Show/hide Expression property, you can also create a "User Defined Javascript event", which is a function that is called whenever the Show/hide expression is evaluated. The javascript function takes two parameters: a flag indicating whether or not the control is visible and a row number. Row number refers to the row for a control, a construct found in Grid components. The UX component doesn't have rows, so row number will always have a value of 1 in a UX component.

Calculated Field Expression

Calculated Field Expressions let you populate a control's value based on the values from other controls in the UX component. The expression can be simple, such as multiplying two numeric fields together. However, sometimes a calculation is more complex than a simple math equation. For example, suppose you wanted to display a person's age based on their birth date. You could create a javascript function to perform the calculation for the Calculated Field Expression. In the Calculated Field Expression, you would call the javascript function, passing the birth date as a parameter (BIRTHDATE is the name of the control containing the birth date)

calcAge(BIRTHDATE)

The function, calcAge, can use the date and time functions in javascript to calculate the age.

function calcAge(birthDate) {
    if (birthDate.length == 0) {
        // no birth date selected
        return 0;
    }
    
    var bDay = new Date(birthDate);
    var today = new Date();
    
    var thisYear = today.getFullYear();
    var bDayThisYear = new Date(thisYear, bDay.getMonth(), bDay.getDate());
    
    var age = thisYear - bDay.getFullYear();
    if (today < bDayThisYear) {
        age = age - 1;
    }        
    return age;
}